<?php

namespace PhpYes\Modules\Cmd;


class CmdList extends SubCmdBase
{
    /** @var string */
    private $name;
    /** @var string */
    private $description;
    /** @var string */
    private $detailDescription;
    /** @var ArgumentDefinition[] */
    private $argumentDefinitions;

    /**
     * CmdList constructor.
     * @param ParentCmdBase $parentCmd
     * @param string|null $alias
     */
    public function __construct(ParentCmdBase $parentCmd, $alias = null)
    {
        $this->name = 'list';
        $this->description = 'list ' . $parentCmd->getName() . ' sub command';
        $this->detailDescription = '';
        $this->argumentDefinitions = array(
            new ArgumentDefinition('help', '-h', '--help', false, false, 'show help information and exit.'),
        );

        parent::__construct($parentCmd, $alias);
    }

    /**
     * @return ArgumentDefinition[]
     */
    public function getArgumentDefinitions()
    {
        return $this->argumentDefinitions;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @return string
     */
    public function getDetailDescription()
    {
        return $this->detailDescription;
    }

    /**
     * 命令的帮助文档
     * NAME
     * SYNOPSIS
     * DESCRIPTION
     * OPTIONS
     * EXAMPLES
     * DISCUSSION
     * ...
     * @return string
     */
    public function help()
    {
        $eol = $this->getLineSeparator();

        return "NAME:{$eol}" . $this->getHangIndent() . $this->getParentCmd()->getName() . ' ' . $this->getAlias() . ' - ' . $this->getDescription() .

        "{$eol}{$eol}SYNOPSIS:{$eol}" . $this->getUsage() .

        "{$eol}{$eol}DESCRIPTION:{$eol}" . $this->getDetailDescription() .
        "{$eol}{$eol}OPTIONS:{$eol}" . $this->getOptionDescription() . $eol;
    }

    /**
     * 执行命令
     * @param int $argc
     * @param array $argv
     * @throws \Exception
     */
    public function execute($argc, $argv)
    {
        if (empty($argc) || empty($argv) || $argc == 1) {
            $listDoc = '';
            $indent = $this->getIndentUnit();
            $eol = $this->getLineSeparator();

            $subCmdList = $this->getParentCmd()->getSubCmdList();
            if ($subCmdList) {
                $first = true;
                foreach ($subCmdList as $alias => $subCmdClass) {
                    /** @var SubCmdBase $subCmd */
                    $subCmd = new $subCmdClass($this->getParentCmd(), $alias);
                    if ($first) {
                        $first = false;
                    } else {
                        $listDoc .= $eol;
                    }

                    $listDoc .= $alias . $indent . $subCmd->getDescription();
                }
            }

            echo $listDoc . $eol;

            return;
        }

        $secondArg = $argv[1];
        $argObj = new ArgumentObject($secondArg, $this);
        if ($argObj->getArgType() == ArgumentObject::ArgTypePosition) {
            throw new CmdException("Unknown argument {$secondArg}");
        } else {
            $argDef = $argObj->getArgumentDefinition();
            $argName = $argDef->getName();
            switch ($argName) {
                case 'help':
                    echo $this->help() . $this->getLineSeparator();
                    break;
                default:
                    break;
            }
        }
    }
}